package com.bwie.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.pojo.TbMenu;
import com.bwie.pojo.TbUser;
import com.bwie.service.TbUserService;
import com.bwie.mapper.TbUserMapper;
import com.bwie.utils.MobileMessageUtil;
import com.bwie.utils.R;
import com.bwie.vo.LoginVo;
import com.bwie.vo.PageInfoVo;
import com.bwie.vo.RegInfoVo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* @author andy
* @description 针对表【tb_user(用户表)】的数据库操作Service实现
* @createDate 2025-07-18 11:23:18
*/
@Service
@Slf4j
public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser>
    implements TbUserService{

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    TbUserMapper tbUserMapper;

    @Autowired
    HttpServletRequest request;

    @Override
    public R sendCode(String mobile) {
        // 手机号校验
        boolean ok = Validator.isMobile(mobile);
        if(!ok) {
            return R.ERROR(500, "手机号错误");
        }


        //--1 生成验证码
        String code = RandomUtil.randomNumbers(4);
        log.info("code=" + code);

        //--2 放入缓存
        String key = "code-" + mobile;
        stringRedisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);

        //--3 发送短信验证码
        MobileMessageUtil.sendMobileMessage(mobile, code);

        return R.OK();
    }

    @Override
    public R userReg(RegInfoVo regInfoVo) {
        //--1 验证手机号是否存在
        TbUser tbUser = tbUserMapper.selectOne(
                new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserMobile, regInfoVo.getMobile())
        );
        if(tbUser != null) {
            return R.ERROR(500, "用户已存在，无法注册！！！！");
        }

        //--2 验证验证码
        String key = "code-" + regInfoVo.getMobile();
        String code = stringRedisTemplate.opsForValue().get(key);
        if(code == null) {
            return R.ERROR(500, "验证码已经过期了");
        }
        // int double
        if(!code.equals(regInfoVo.getCode())) {
            return R.ERROR(500, "验证码错误");
        }

        //--3 加密密码
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String hashPass = encoder.encode(regInfoVo.getPass());
        log.info("加密密码为：" + hashPass);

        //--4 用户注册
        TbUser user = new TbUser();
        user.setUserPass(hashPass);
        user.setUserMobile(regInfoVo.getMobile());
        user.setUserName("匿名用户");

        user.setCreateTime(new Date());
        user.setCreateBy("系统");

        tbUserMapper.insert(user);

        return R.OK();
    }

    @Override
    public R userLogin(LoginVo loginVo) {
        //--1 根据手机号获取用户信息
        TbUser tbUser = tbUserMapper.selectOne(
                new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserMobile, loginVo.getMobile())
        );
        if(tbUser == null) {
            return R.ERROR(500, "用户不存在");
        }

        //--2 校验密码
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        // 第一个参数为明文密码，第二个参数为加密密码
        boolean check = encoder.matches(loginVo.getPass(), tbUser.getUserPass());
        if(!check) {
            return R.ERROR(500, "密码错误");
        }

        //--3 生成token并存入缓存，并设置过期时间
        String token = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "123456")
                .claim("userId", tbUser.getUserId())
                .claim("userName", tbUser.getUserName())
                .compact();
        String key = token;
        // K = V
        stringRedisTemplate.opsForValue().set(key, token, 60, TimeUnit.MINUTES);

        //--4 获取当前用户的角色列表（权限菜单）
        List<String> roleList = tbUserMapper.getRoleList(tbUser.getUserId());
        tbUser.setRoleList(roleList);

        //--5 返回token以及用户信息
        tbUser.setToken(token);
        tbUser.setUserPass(null);

        return R.OK(tbUser);
    }

    @Override
    public R getMenuTree() {
        String token = request.getHeader("token");
        // isEmpty (token==null || token=='')
        if(StringUtils.isEmpty( token)) {
            return R.ERROR(500, "请先登录");
        }
        Claims body = Jwts.parser().setSigningKey("123456").parseClaimsJws(token).getBody();
        Integer userId = body.get("userId", Integer.class);

        //--1 获取当前用户菜单列表
        List<TbMenu> tbMenuList = tbUserMapper.selecMenutListByUserId(userId);

        //--2 组装菜单树
        List<Tree<String>> trees = TreeUtil.build(tbMenuList, "0", (tree, node) -> {
            node.setId(""+tree.getMenuId());
            node.setName(tree.getMenuName());
            node.setParentId(""+tree.getMenuPid());

            node.putExtra("path", tree.getMenuPath());
        });


        return R.OK(trees);
    }

    @Override
    public R getShopperList(PageInfoVo pageInfoVo) {
        //--1 构造分页参数
        Page<TbUser> page = new Page<>(pageInfoVo.getPageNum(), pageInfoVo.getPageSize());

        //--2 查询分页数据
        Page<TbUser> userList = tbUserMapper.getShopperList(page, pageInfoVo);

        return R.OK(userList);
    }
}




